import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 用反射和表驱动来调用构造方法
 * 目的是避免 难以维护的 if/else
 *
 * @author loafer
 */
public class DataFactory {


    private static final ReentrantLock LOCK = new ReentrantLock(true);
    private static final HashMap<Byte, Class<? extends BaseInformationElement>> TYPE_CLASS_HASH_MAP = new HashMap<>();
    private DataFactory() {
        // nop
    }
    private static final ConcurrentHashMap<Class<? extends BaseInformationElement>, Constructor<? extends BaseInformationElement>> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>();

    static {

        TYPE_CLASS_HASH_MAP.put((byte)0x01,ConsumData.class);

    }
    public final static Class<? extends BaseInformationElement> getClass(byte type) {
        if (!TYPE_CLASS_HASH_MAP.containsKey(type)) {
            throw new RuntimeException("未定义的命令!" + type);
        }
        return TYPE_CLASS_HASH_MAP.get(type);
    }

    public final static  <T extends BaseInformationElement> T deserialize(Class<T> clazz , ByteBuffer byteBuffer) {
        if (null == clazz) {
            throw new RuntimeException("未定义的命令!");
        }
        try {
            Constructor constructor = CONSTRUCTOR_CACHE.get(clazz);
            if (constructor == null) {
                // 确保多线程情况下只要调用一次反射的构造方法
                LOCK.lock();
                try {
                    // 需要多判断一次是否为空
                    if (CONSTRUCTOR_CACHE.get(clazz) == null) {
                        Constructor c = clazz.getConstructor(ByteBuffer.class);
                        c.setAccessible(true);
                        //cache Constructor
                        CONSTRUCTOR_CACHE.put(clazz, c);
                        constructor = c;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 避免死锁
                    LOCK.unlock();
                }

            }
            return (T) constructor.newInstance(byteBuffer);
        } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
    }


